# 从 Django 的 contrib 模块中导入 admin 模块，用于自定义 Django 管理界面
from django.contrib import admin
# 导入 Django 的表单模块，用于创建和处理表单
from django import forms
# 从 Django 的 contrib.admin.widgets 模块中导入 FilteredSelectMultiple 小部件，用于多选过滤
from django.contrib.admin.widgets import FilteredSelectMultiple
# 从 Django 的 contrib.auth.forms 模块中导入 ReadOnlyPasswordHashField，用于显示只读的密码哈希值
from django.contrib.auth.forms import ReadOnlyPasswordHashField
# 从 Django 的 contrib.auth.admin 模块中导入 UserAdmin 并重命名为 BaseUserAdmin，用于自定义用户管理界面
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

# 从 accounts 应用的 models 模块中导入所需的模型类
from accounts.models import (Consumer, Permission, Role, StorageMenu, Department, config)

# 定义一个用于创建新用户的表单类
class ConsumerCreationForm(forms.ModelForm):
    """
    这个表单类用于创建新用户。
    包含所有必需的字段，以及一个重复的密码字段用于确认密码。
    """
    # 定义密码输入字段，使用 PasswordInput 小部件以隐藏输入内容
    password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
    # 定义密码确认输入字段，同样使用 PasswordInput 小部件
    password2 = forms.CharField(
        label="Password confirmation", widget=forms.PasswordInput
    )

    class Meta:
        # 指定该表单关联的模型为 Consumer
        model = Consumer
        # 定义表单字段的小部件，这里将 groups 字段使用 FilteredSelectMultiple 小部件
        widgets = {
            "groups": FilteredSelectMultiple,
        }
        # 指定表单要显示的字段
        fields = ("username", "date_joined")

    # 自定义密码确认字段的验证方法
    def clean_password2(self):
        # 获取用户输入的密码
        password1 = self.cleaned_data.get("password1")
        # 获取用户输入的确认密码
        password2 = self.cleaned_data.get("password2")
        # 如果密码和确认密码都有输入且不相等，则抛出验证错误
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords dont't match")
        return password2

    # 重写 save 方法，用于保存用户信息并设置密码
    def save(self, commit=True):
        # 调用父类的 save 方法，先不提交到数据库
        user = super().save(commit=False)
        # 使用 set_password 方法将用户输入的密码进行哈希处理
        user.set_password(self.cleaned_data["password1"])
        # 如果 commit 为 True，则将用户信息保存到数据库
        if commit:
            user.save()
        return user

# 定义一个用于修改用户信息的表单类
class ConsumerChangeForm(forms.ModelForm):
    # 使用 ReadOnlyPasswordHashField 显示只读的密码哈希值
    password = ReadOnlyPasswordHashField()

    class Meta:
        # 指定该表单关联的模型为 Consumer
        model = Consumer
        # 定义表单字段的小部件，这里将 groups 字段使用 FilteredSelectMultiple 小部件
        widgets = {
            "groups": FilteredSelectMultiple("groups", 1),
        }
        # 指定表单要显示的字段
        fields = (
            "username",
            "password",
            "mobile",
            "email",
            "is_delete",
            "is_active",
            "is_staff",
            "is_admin",
        )

    # 自定义密码字段的验证方法，返回初始的密码哈希值
    def clean_password(self):
        # 无论用户输入什么，都返回初始的密码哈希值
        # 因为该字段无法直接访问初始值，所以在这里处理
        return self.initial["password"]

# 定义一个自定义的用户管理类，继承自 BaseUserAdmin
class ConsumerAdmin(BaseUserAdmin):
    # 指定修改用户信息时使用的表单类
    form = ConsumerChangeForm
    # 指定创建用户时使用的表单类
    add_form = ConsumerCreationForm

    # 定义在用户列表页面显示的字段
    list_display = (
        "id",
        "username",
        "category",
        "name",
        "mobile",
        "email",
        "is_active",
        "belong_system",
        "status",
    )

    # 定义用户信息编辑页面的字段分组
    fieldsets = (
        # 登录信息分组，包含用户名、用户类别和密码字段
        ("登录信息", {"fields": ("username", "category", "password")}),
        # 基本信息分组，包含姓名、手机号码等多个字段
        (
            "基本信息",
            {
                "fields": (
                    "name",
                    "mobile",
                    "sex",
                    "email",
                    "avator",
                    "belong_role",
                    "belong_department",
                    "is_delete",
                    "salt",
                    "belong_system",
                    "status",
                )
            },
        ),
        # 系统权限分组，包含管理员权限、激活状态和员工状态字段
        ("系统权限", {"fields": ("is_admin", "is_active", "is_staff")}),
        # 数据权限分组，包含用户组字段
        ("数据权限", {"fields": ("groups",)}),
    )

    # 定义创建用户页面的字段分组
    add_fieldsets = (
        (
            None,
            {
                # 定义该分组的 CSS 类，这里使用 wide 和 extrapretty 类
                "classes": ("wide", "extrapretty"),
                # 定义该分组要显示的字段，包括用户名、密码和密码确认字段
                "fields": ("username", "password1", "password2"),
            },
        ),
    )

    # 定义搜索框可搜索的字段，这里为姓名和手机号码
    search_fields = ("name", "mobile")
    # 定义列表页面的过滤条件，这里为用户类别
    list_filter = ("category",)
    # 定义列表页面的排序字段，这里为姓名
    ordering = ("name",)
    # 定义水平过滤的字段，这里为空
    filter_horizontal = ()

# 定义一个自定义的权限管理类，继承自 admin.ModelAdmin
class PermissionAdmin(admin.ModelAdmin):
    # 定义在权限列表页面显示的字段
    list_display = ("id", "code", "name", "intro", "status", "creator", "created")
    # 定义权限列表页面的过滤条件，这里为状态
    list_filter = ("status",)
    # 定义搜索框可搜索的字段，这里为权限代码和名称
    search_fields = ("code", "name")

# 定义一个自定义的部门管理类，继承自 admin.ModelAdmin
class DepartmentAdmin(admin.ModelAdmin):
    # 定义在部门列表页面显示的字段
    list_display = ("id", "code", "name", "describe", "belong_system")
    # 定义部门列表页面的过滤条件，这里暂时注释掉
    # list_filter = ("status",)
    # 定义搜索框可搜索的字段，这里为部门代码和名称
    search_fields = ("code", "name")

# 定义一个自定义的配置管理类，继承自 admin.ModelAdmin
class configAdmin(admin.ModelAdmin):
    # 定义在配置列表页面显示的字段
    list_display = ("id", "name", "logo_file", "desc", "status")
    # 定义配置列表页面的过滤条件，这里暂时注释掉
    # list_filter = ("status",)
    # 定义搜索框可搜索的字段，这里为状态和名称
    search_fields = ("status", "name")

# 定义一个自定义的角色管理类，继承自 admin.ModelAdmin
class RoleAdmin(admin.ModelAdmin):
    # 定义在角色列表页面显示的字段
    list_display = ("id", "code", "name", "intro", "status", "creator", "created")
    # 定义角色列表页面的过滤条件，这里为状态
    list_filter = ("status",)
    # 定义搜索框可搜索的字段，这里为角色代码和名称
    search_fields = ("code", "name")

# 定义一个自定义的菜单管理类，继承自 admin.ModelAdmin
class MenuAdmin(admin.ModelAdmin):
    # 定义在菜单列表页面显示的字段
    list_display = (
        "id",
        "menuName",
        "belong_sys",
        "parentPath",
        "icon",
        "menuUrl",
        "localFilePath",
        "cacheable",
        "affix",
        "order",
    )
    # 定义在菜单列表页面可编辑的字段
    list_editable = [
        "menuName",
        "icon",
        "belong_sys",
        "parentPath",
        "menuUrl",
        "order",
        "localFilePath",
        "cacheable",
        "affix",
    ]
    # 定义菜单列表页面的过滤条件，这里为状态和所属系统
    list_filter = ("status", "belong_sys")
    # 定义搜索框可搜索的字段，这里为菜单 URL 和菜单名称
    search_fields = ("menuUrl", "menuName")

# 设置 Django 管理界面的头部显示文本
admin.site.site_header = "基础环境"
# 设置 Django 管理界面的标题显示文本
admin.site.site_title = "基础环境"
# 注册 Consumer 模型，使用自定义的 ConsumerAdmin 管理类
admin.site.register(Consumer, ConsumerAdmin)
# 注册 config 模型，使用自定义的 configAdmin 管理类
admin.site.register(config, configAdmin)
# 注册 Permission 模型，使用自定义的 PermissionAdmin 管理类
admin.site.register(Permission, PermissionAdmin)
# 注册 Department 模型，使用自定义的 DepartmentAdmin 管理类
admin.site.register(Department, DepartmentAdmin)
# 注册 Role 模型，使用自定义的 RoleAdmin 管理类
admin.site.register(Role, RoleAdmin)
# 注册 StorageMenu 模型，使用自定义的 MenuAdmin 管理类
admin.site.register(StorageMenu, MenuAdmin)
